package com.binhthuan.catechist.server.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.scb.gwt.web.server.i18n.GWTI18N;

import com.binhthuan.catechist.client.ECConstants;
import com.binhthuan.catechist.client.ECMessages;
import com.binhthuan.catechist.server.ErrorObject;
import com.binhthuan.catechist.shared.constant.Operation;
import com.binhthuan.catechist.shared.constant.Parameter;

/**
 * @author Giang Đinh - Lớp servlet trừu tượng, mọi servlet của ứng dụng phải
 *         được kế thừa từ lớp này.
 * 
 */
public abstract class AbstractServlet extends HttpServlet {

    // Response statuses.
    public static int STATUS_FAILURE = -1;
    public static int STATUS_LOGIN_INCORRECT = -5;
    public static int STATUS_LOGIN_REQUIRED = -7;
    public static int STATUS_LOGIN_SUCCESS = -8;
    public static int STATUS_MAX_LOGIN_ATTEMPTS_EXCEEDED = -6;
    public static int STATUS_SERVER_TIMEOUT = -100;
    public static int STATUS_SUCCESS = 0;
    public static int STATUS_TRANSPORT_ERROR = -90;
    public static int STATUS_VALIDATION_ERROR = -4;

    private static ECConstants constant;
    private static ECMessages message;
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    protected static Logger logger = Logger.getLogger(AbstractServlet.class);
    private PrintWriter out;

    protected SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
    protected SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    /**
     * 
     */
    public AbstractServlet() {
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        processRequest(request, response);
    }

    @SuppressWarnings("unchecked")
    public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        System.err.println(request.getQueryString());
        System.err.println("--------------- Received request ---------------");

        Enumeration<String> names = request.getParameterNames();

        while (names.hasMoreElements()) {
            String str = names.nextElement();
            String[] values = request.getParameterValues(str);
            String msg = str;
            if (values.length == 1) {
                String paramValue = values[0];
                if (paramValue.length() == 0)
                    msg = msg + ": " + "NULL";
                else
                    msg = msg + ": " + paramValue;
            } else {
                msg = msg + ": ";
                for (int i = 0; i < values.length; i++) {
                    msg = msg + values[i] + ",";
                }
            }

            System.err.println(msg);
        }
        System.err.println("********** End request **********");
        logger.info("Received request from: " + request.getRemoteHost());
        String operation = request.getParameter(Parameter.OPERATION);

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        this.out = response.getWriter();

        if (operation == null) {
            logger.info("Missing operation's information from: " + request.getRemoteHost());
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Missing operation's information");
        } else if (operation.equals(Operation.FETCH)) {
            fetch(request, response);
        } else if (operation.equals(Operation.ADD)) {
            add(request, response);
        } else if (operation.equals(Operation.UPDATE)) {
            update(request, response);
        } else if (operation.equals(Operation.REMOVE)) {
            boolean confirmation = request.getParameter(ErrorObject.REQUIRE_CONFIRMATION) == null ? false:Boolean.parseBoolean(request.getParameter(ErrorObject.REQUIRE_CONFIRMATION));
            remove(request, response, confirmation);
        } else {
            logger.info("Received unknown operation from: " + request.getRemoteHost());
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Missing operation's information");
        }
    }

    protected abstract void fetch(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException;

    protected abstract void add(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException;

    protected abstract void update(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException;

    protected abstract void remove(HttpServletRequest request, HttpServletResponse response, boolean confirmation) throws ServletException,
            IOException;

    /**
     * Gửi 1 chuỗi về cho người dùng.
     * 
     * @param response
     */
    public void sendResponse(String response) {
        System.err.println(response);
        out.write(response);
        out.flush();
    }

    public ECMessages getMessagesFactory() throws IOException {
        if (message == null) {
            message = GWTI18N.create(ECMessages.class);
        }

        return message;
    }

    public ECConstants getConstantsFactory() throws IOException {
        if (constant == null) {
            constant = GWTI18N.create(ECConstants.class);
        }

        return constant;
    }

    public boolean checkSortASC(String sortByString) {
        return !(sortByString != null && sortByString.indexOf('-') == 0);
    }

    public String getSortingColumn(String sortByString) {
        if (sortByString != null && sortByString.indexOf('-') == 0) {
            return sortByString.substring(1);
        }

        return sortByString;
    }

    public String getRealPath(String relativePath) {
        return getServletContext().getRealPath(relativePath);
    }
}
